/*---------------------------------------
* Author:ZJ
* createDate:Tuesday, August 07, 2012
* Description:
*
------------------------------------------*/


#include "StdAfx.h"
#include "connection.hpp"
#include "connection_manager.hpp"

namespace fly {

	namespace jld{

		namespace server {

			connection::connection(boost::asio::io_service& io_service,
				connection_manager& manager, handler* handler)
				: socket_(io_service),
				connection_manager_(manager),
				handler_(handler),
				recv_buf_(),
				send_buf_(),
				conn_info_()
			{
			}

			connection::~connection()
			{		
				LOG_PRINTF("Destroy connection");
			}

			boost::asio::ip::tcp::socket& connection::socket()
			{
				return socket_;
			}

			conn_info& connection::info()
			{
				return conn_info_;
			}

			void connection::start()
			{
				read_header();
			}

			void connection::stop()
			{
				socket_.close();
			}

			void connection::read_header()
			{
				async_read(socket_, recv_buf_.buf(), asio::transfer_exactly(recv_buf_.header_size()),
					boost::bind(&connection::handle_header_read, shared_from_this(),
					boost::asio::placeholders::error,
					boost::asio::placeholders::bytes_transferred));
			}

			void connection::handle_header_read(const boost::system::error_code& e,
				std::size_t bytes_transferred)
			{
				if(e)
				{
					LOG_T_ERR(e.message());
					connection_manager_.stop(shared_from_this());
					return;
				}

				if (!recv_buf_.handle_header())
				{
					LOG_ERR("Handle header faild");
					connection_manager_.attack(shared_from_this());
					return;
				}
				read_body();
			}

			void connection::read_body()
			{
				async_read(socket_, recv_buf_.buf(), asio::transfer_exactly(recv_buf_.body_size()),
					boost::bind(&connection::handle_body_read, shared_from_this(),
					boost::asio::placeholders::error,
					boost::asio::placeholders::bytes_transferred));
			}

			void connection::handle_body_read(const boost::system::error_code& e,
				std::size_t bytes_transferred)
			{
				if(e)
				{
					LOG_T_ERR(e.message());
					connection_manager_.stop(shared_from_this());
					return;
				}
				if (!handler_->handle_recv(recv_buf_, send_buf_, conn_info_))
				{
					LOG_ERR("Handle recv_buf faild");
					connection_manager_.attack(shared_from_this());
					return;
				}
				if (send_buf_.is_send())
				{
					connection_manager_.send(shared_from_this(), send_buf_.packets());
				}
				read_header();	
			}

			void connection::asyn_write(const_buf_ptr send_buf)
			{
				boost::asio::async_write(socket_, *send_buf,
					boost::bind(&connection::handle_write, shared_from_this(),
					boost::asio::placeholders::error, send_buf));
			}

			void connection::handle_write(const boost::system::error_code& e, const_buf_ptr const_send_buf)
			{
				if (e)
				{
					LOG_T_ERR(e.message());
					connection_manager_.stop(shared_from_this());
					return;
				}
			}		

		} // namespace server
	}
} // namespace servspace
